package com.smasher.domain.activity

import android.annotation.SuppressLint
import android.content.DialogInterface
import android.util.Log
import android.view.View
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.smasher.core.log.Logger
import com.smasher.core.log.ToastUtil
import com.smasher.domain.R
import com.smasher.domain.adapter.DomainAdapter
import com.smasher.domain.databinding.ActivityDomainBinding
import com.smasher.domain.entity.BeanDomain
import com.smasher.domain.fragment.DeleteDialog
import com.smasher.domain.fragment.DomainFragment
import com.smasher.domain.fragment.DomainFragment.OnAddListener
import com.smasher.domain.helper.DomainHelper
import com.smasher.widget.listener.OnItemClickListener
import kotlinx.coroutines.launch

/**
 * @author HXZ_Android
 */
abstract class DomainActivity : LoadFirstActivity(),
    View.OnClickListener,
    OnItemClickListener,
    OnAddListener {

    private val mAdapter = DomainAdapter()
    private val action = BeanDomain(
        id = -1, name = "", scheme = "", host = "", port = 0
    )

    private lateinit var mBinding: ActivityDomainBinding

    override fun getRootView(): View {
        mBinding = ActivityDomainBinding.inflate(layoutInflater)
        return mBinding.root
    }

    override fun initView() {
        mBinding.toolbar.setNavigationOnClickListener { finish() }
        mBinding.recyclerView.layoutManager = LinearLayoutManager(this)
        mBinding.recyclerView.adapter = mAdapter
        mBinding.submit.setOnClickListener(this)
        mAdapter.setOnItemClickListener(this)
    }

    override fun initData() {
        loadFromJSON()
        lifecycleScope.launch {
            domainViewModel.domainList.observe(this@DomainActivity) { beanDomains ->
                Logger.d(TAG, "observe Data: $beanDomains")
                domains.clear()
                domains.addAll(beanDomains)
                bindDomainList()
            }
        }
    }


    private fun bindDomainList() {
        val domainCurrent = getCurrent()
        if (domainCurrent != null) {
            if (!domains.contains(domainCurrent)) {
                Logger.e(TAG, "save single: $domainCurrent")
                saveDomain(domainCurrent) {
                    Logger.e(TAG, "save single: success")
                }
            } else {
                updateView(domainCurrent)
            }
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun updateView(current: BeanDomain) {
        val position = domains.indexOf(current)
        if (position > -1) {
            val select = domains[position]
            select.select = true
        }

        domains.add(action)
        mAdapter.setData(domains)
        mAdapter.notifyDataSetChanged()
    }

    override fun onClick(v: View) {
        val id = v.id
        if (id == R.id.submit) {
            val domain = getSelected()
            if (domain != null) {
                updateBeanDomain(domain)
                setResult(RESULT_OK)
                finish()
            } else {
                ToastUtil.warning(this, R.string.app_domain_select)
            }
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onClick(view: View, i: Int) {
        Log.i(TAG, "onClick: $i")
        val domain = mAdapter.getItem(i) ?: return
        val id = domain.id
        if (id == -1) {
            showCreateDialog()
        } else {
            resetState()
            domain.select = true
            mAdapter.notifyDataSetChanged()
        }
    }

    override fun onLongClick(view: View, i: Int) {
        showDeleteDialog { dialog, which ->
            Log.d(TAG, "dialog=$dialog which=$which")
            deleteDomain(i)
        }
    }

    override fun onEditFinish(view: View, i: Int, s: String) {}


    override fun onAdd(domain: BeanDomain) {
        saveDomain(domain) {
            Logger.e(TAG, "onAdd: success = $it")
        }
    }


    private fun showCreateDialog() {
        var dialog = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG_CREATE)
        if (dialog == null) {
            dialog = DomainFragment.newInstance()
        }
        if (dialog is DomainFragment) {
            dialog.setOnAddListener(this)
            if (!dialog.isAdded) {
                dialog.show(supportFragmentManager, FRAGMENT_TAG_CREATE)
            }
        }
    }

    private fun showDeleteDialog(deleteListener: DialogInterface.OnClickListener) {
        var dialog = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG_DELETE)
        if (dialog == null) {
            dialog = DeleteDialog.newInstance()
        }
        if (dialog is DeleteDialog) {
            dialog.setPositiveListener(deleteListener)
            dialog.setNegativeListener { _, which ->
                Log.d(TAG, "which=$which")
            }
            if (!dialog.isAdded) {
                dialog.show(supportFragmentManager, FRAGMENT_TAG_DELETE)
            }
        }
    }

    private fun deleteDomain(index: Int) {
        lifecycleScope.launch {
            val item = mAdapter.getItem(index)
            domainViewModel.deleteSingle(item) {
                if (it) {
                    loadDomainList()
                } else {
                    ToastUtil.warning(this@DomainActivity, "删除失败")
                }
            }
        }
    }

    private fun resetState() {
        for (domain in domains) {
            domain.select = false
        }
    }

    public override fun loadDomainList() {
        Logger.i("load domain list in main thread")
        domainViewModel.queryList()
    }

    private fun getSelected(): BeanDomain? {
        var select: BeanDomain? = null
        for (domain in domains) {
            if (domain.select) {
                select = domain
                break
            }
        }
        return select
    }

    private fun getCurrent(): BeanDomain? {
        val domainTemp = DomainHelper.getInstance().currentDomain
        if (domainTemp != null) {
            domainTemp.select = true
        }
        return domainTemp
    }

    private fun updateBeanDomain(domain: BeanDomain) {
        DomainHelper.getInstance().currentDomain = domain
        onDomainChange(domain)
    }

    /**
     * domainChange
     *
     * @param domain domain
     */
    protected abstract fun onDomainChange(domain: BeanDomain)

    companion object {
        private const val FRAGMENT_TAG_DELETE = "FRAGMENT_TAG_DELETE"
        private const val FRAGMENT_TAG_CREATE = "FRAGMENT_TAG_CREATE"
    }
}